﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using JetBrains.Annotations;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
using System.Diagnostics;

namespace TuanHA_Combat_Routine
{
    public partial class Classname : CombatRoutine
    {
        //[DllImport("user32.dll")]
        //private static extern IntPtr GetForegroundWindow();

        //[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        //private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        //private string GetActiveWindowTitle()
        //{
        //    const int nChars = 256;
        //    IntPtr handle = IntPtr.Zero;
        //    StringBuilder Buff = new StringBuilder(nChars);
        //    handle = GetForegroundWindow();

        //    if (GetWindowText(handle, Buff, nChars) > 0)
        //    {
        //        return Buff.ToString();
        //    }
        //    return null;
        //}

        #region Delegates

        public delegate WoWPoint LocationRetriverDelegate(object context);

        #endregion

        #region Basic Functions

        public override bool WantButton
        {
            get { return true; }
        }

        public override WoWClass Class
        {
            get { return WoWClass.DeathKnight; }
        }

        public override string Name
        {
            get { return "TuanHA Death Knight [Special Edition]"; }
        }

        //public override Composite RestBehavior
        //{
        //    get { return RestRotation(); }
        //}

        public override Composite PreCombatBuffBehavior
        {
            get { return MainRotation(); }
        }

        //public override Composite PullBuffBehavior
        //{
        //    get { return MainRotation(); }
        //}

        //public override Composite PullBehavior
        //{
        //    get { return MainRotation(); }
        //}

        //public override Composite CombatBuffBehavior
        //{
        //    get { return MainRotation(); }
        //}

        public override Composite CombatBehavior
        {
            get { return MainRotation(); }
        }

        //public override Composite HealBehavior
        //{
        //    get { return MainRotation(); }
        //}

        //public override Composite MoveToTargetBehavior
        //{
        //    get { return CreateMoveToLosBehavior(); }
        //}

        private static LocalPlayer Me
        {
            get { return StyxWoW.Me; }
        }

        //public override void Initialize()
        //{
        //    Logging.Write("");
        //    Logging.Write("Hello level " + Me.Level + " " + Me.Race + " " + Me.Class);
        //    Logging.Write("");
        //    Logging.Write("Thank you for using TuanHA Death Knight Special Edition");
        //    Logging.Write("");
        //    Logging.Write("For best Combat Routine performance, please use Tyrael botbase.");
        //    Logging.Write("You can download Tyrael Here: http://goo.gl/51E0F6");
        //    Logging.Write("FRAMELOCK is now supported within Combat Routine");
        //    Logging.Write("Click Class Config - General Settings Tab - Check Enable Framelock");
        //    Logging.Write("For detailed installation guide, visit our new website");
        //    Logging.Write("www.tuanha.biz");
        //    Logging.Write("");

        //    //Disable for speed
        //    Lua.Events.AttachEvent("ACTIVE_TALENT_GROUP_CHANGED", UpdateStatusEvent);
        //    Lua.Events.AttachEvent("PLAYER_TALENT_UPDATE", UpdateMyTalentEvent);
        //    Lua.Events.AttachEvent("GLYPH_ADDED", UpdateMyGlyphEvent);
        //    //Lua.Events.AttachEvent("WORLD_MAP_NAME_UPDATE", UpdateRaidPartyMembersEvent);
        //    //Lua.Events.AttachEvent("RAID_ROSTER_UPDATE", UpdateRaidPartyMembersEvent);
        //    Lua.Events.AttachEvent("ZONE_CHANGED_NEW_AREA", ClearEnemyandFriendListCacheEvent);

        //    //BotEvents.Player.OnMapChanged += UpdateCurrentMapEvent;
        //    BotEvents.OnBotStarted += OnBotStartedEvent;

        //    //Set Camera angle so you never have problem with it
        //    //console cameraSmoothTrackingStyle 0 (credit by alxaw - member of CLU dev team) 
        //    //Lua.DoString("RunMacroText(\"/console cameraSmoothTrackingStyle 1\")");
        //    NeedResetPresence = true;
        //    THSettings.Instance.UpdateStatus = true;
        //}
        public override void Initialize()
        {
            Styx.Common.Logging.Write("");
            Styx.Common.Logging.Write(string.Concat(new object[] { "Hello level ", Me.Level, " ", Me.Race, " ", Me.Class }));
            Styx.Common.Logging.Write("");
            Styx.Common.Logging.Write("Thank you for using TuanHA Death Knight Special Edition");
            Styx.Common.Logging.Write("");
            Styx.Common.Logging.Write("For best Combat Routine performance, please set Custom Lag Tolerance to 400 ms.");
            Styx.Common.Logging.Write("Game Menu > Interface > Combat Check Custom Lag Toerance and Adjust the Slider to 400 ms");
            Styx.Common.Logging.Write("Best Non-AFK Botbase are LazyRaider: http://goo.gl/nf0zab or Tyrael http://goo.gl/51E0F6");
            Styx.Common.Logging.Write("For detailed installation guide, visit our new website (Google TuanHA");
            Styx.Common.Logging.Write("");
            Lua.Events.AttachEvent("ACTIVE_TALENT_GROUP_CHANGED", new LuaEventHandlerDelegate(Classname.UpdateStatusEvent));
            Lua.Events.AttachEvent("PLAYER_TALENT_UPDATE", new LuaEventHandlerDelegate(Classname.UpdateMyTalentEvent));
            Lua.Events.AttachEvent("GLYPH_ADDED", new LuaEventHandlerDelegate(Classname.UpdateMyGlyphEvent));
            BotEvents.OnBotStarted += new BotEvents.OnBotStartDelegate(Classname.OnBotStartedEvent);
            PetSpells.Clear();
            this.PreBuffSelector();
            this.RotationSelector();
            //this.RestSelector();
            this.DeathSelector();
            THSettings.Instance.UpdateStatus = true;
        }

        public override void OnButtonPress()
        {
            var gui = new THDKForm();
            gui.ShowDialog();
        }

        #endregion

        #region Function After this Region Order Alphabetically

        #endregion

        #region GetUnits

        //private static IEnumerable<WoWUnit> GetAllUnits()
        //{
        //    return ObjectManager.GetObjectsOfType<WoWUnit>(true, true)
        //                        .Where(
        //                            unit =>
        //                            !Blacklist.Contains(unit.Guid, BlacklistFlags.All) &&
        //                            unit.Attackable &&
        //                            unit.CanSelect &&
        //                            unit.IsAlive &&
        //                            unit.DistanceSqr <= 3600)
        //                        .ToList();
        //}
        private static IEnumerable<WoWUnit> GetAllUnits()
        {
            return ObjectManager.GetObjectsOfType<WoWUnit>(true, true);
        }

        private static readonly List<WoWUnit> FarFriendlyPlayers = new List<WoWUnit>();
        private static readonly List<WoWUnit> FarFriendlyUnits = new List<WoWUnit>();
        private static readonly List<WoWUnit> NearbyFriendlyPlayers = new List<WoWUnit>();
        private static readonly List<WoWUnit> NearbyFriendlyUnits = new List<WoWUnit>();
        private static readonly List<WoWUnit> NearbyUnFriendlyPlayers = new List<WoWUnit>();
        private static readonly List<WoWUnit> NearbyUnFriendlyUnits = new List<WoWUnit>();
        private static readonly List<WoWUnit> FarUnFriendlyPlayers = new List<WoWUnit>(); //Don't use in this CC
        private static readonly List<WoWUnit> FarUnFriendlyUnits = new List<WoWUnit>();

        private static Composite GetUnits()
        {
            return new Styx.TreeSharp.Action(delegate(object param0)
            {
                NearbyFriendlyPlayers.Clear();
                NearbyFriendlyUnits.Clear();
                FarFriendlyPlayers.Clear();
                FarFriendlyUnits.Clear();
                NearbyUnFriendlyPlayers.Clear();
                NearbyUnFriendlyUnits.Clear();
                FarUnFriendlyPlayers.Clear();
                FarUnFriendlyUnits.Clear();
                foreach (WoWUnit unit in GetAllUnits())
                {
                    if (((!Blacklist.Contains(unit.Guid, BlacklistFlags.All) && unit.IsAlive) && (unit.CanSelect && !unit.IsPet)) && (unit.Distance <= 60.0))
                    {
                        if (IsMyPartyRaidMember(unit))
                        {
                            WoWPlayer player = unit as WoWPlayer;
                            if ((player != null) || NeedHealUnit(unit))
                            {
                                FarFriendlyPlayers.Add(unit);
                                FarFriendlyUnits.Add(unit);
                                if (unit.Distance <= 40.0)
                                {
                                    NearbyFriendlyUnits.Add(unit);
                                    NearbyFriendlyPlayers.Add(unit);
                                }
                            }
                            else
                            {
                                FarFriendlyUnits.Add(unit);
                                if (unit.Distance <= 40.0)
                                {
                                    NearbyFriendlyUnits.Add(unit);
                                }
                            }
                        }
                        else if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
                        {
                            WoWPlayer player2 = unit as WoWPlayer;
                            if (player2 != null)
                            {
                                FarUnFriendlyPlayers.Add(unit);
                                FarUnFriendlyUnits.Add(unit);
                                if (unit.Distance <= 40.0)
                                {
                                    NearbyUnFriendlyUnits.Add(unit);
                                    NearbyUnFriendlyPlayers.Add(unit);
                                }
                            }
                            else
                            {
                                FarUnFriendlyUnits.Add(unit);
                                if (unit.Distance <= 40.0)
                                {
                                    NearbyUnFriendlyUnits.Add(unit);
                                }
                            }
                        }
                        else if (((!unit.IsFriendly && unit.Attackable) && !unit.IsQuestGiver) || ((Me.Combat && IsDummy(unit)) && Me.IsFacing(unit)))
                        {
                            WoWPlayer player3 = unit as WoWPlayer;
                            if (((!IsUsingAFKBot && (player3 != null)) && (player3.Combat && (player3.CurrentTarget != null))) && (player3.CurrentTarget == Me))
                            {
                                FarUnFriendlyPlayers.Add(unit);
                                FarUnFriendlyUnits.Add(unit);
                                if (unit.Distance <= 40.0)
                                {
                                    NearbyUnFriendlyUnits.Add(unit);
                                    NearbyUnFriendlyPlayers.Add(unit);
                                }
                            }
                            else
                            {
                                FarUnFriendlyUnits.Add(unit);
                                if (unit.Distance <= 40.0)
                                {
                                    NearbyUnFriendlyUnits.Add(unit);
                                }
                            }
                        }
                    }
                }
                return RunStatus.Failure;
            });
        }

        #endregion

        #region Hold@

        private static Composite Hold()
        {
            return new Decorator(delegate(object ret)
            {
                if ((((Me.IsValid && StyxWoW.IsInWorld) && Me.IsAlive) && (THSettings.Instance.AttackOOC || Me.Combat)) && (!MeHasAura("Food") || (HealWeight(Me) >= THSettings.Instance.DoNotHealAbove)))
                {
                    return MeHasAura("Resurrection Sickness");
                }
                return true;
            }, new Styx.TreeSharp.Action(delegate(object param0)
            {
                if (Me.IsAutoAttacking)
                {
                    Lua.DoString("RunMacroText('/stopattack');", "WoW.lua");
                }
                Styx.Common.Logging.Write("Hold on Eat/Drink/Dead/Not in Game/Sesurrection Sickness/Attack Out of Combat");
                return RunStatus.Success;
            }));
        }

        #endregion

        #region Pulse

        private static DateTime LastSwitch;
        private static DateTime BurstLast;
        private static bool Burst = false;

        public override void Pulse()
        {
            if (StyxWoW.IsInWorld && BasicCheck(Me))
            {
                if (THSettings.Instance.UpdateStatus)
                {
                    UpdateStatus();
                }
                else
                {
                    GlobalCheck();
                    //ReturningFlag();
                    if (!Me.Mounted)
                    {
                        LichborneFearVoid();//纯粹用巫妖之躯解恐惧
                        DeathGripInterruptVoid();//施法者5码外,除了5个法术外,其他都会断,免疫打断时也会拉断
                        MindFreezeVoid();//能断就断
                        ArcaneTorrentVoid();//血精灵天赋打断
                        StrangulateVoid();
                        AsphyxiateVoid();//30码打断,但没有了血量的判断了?
                        GorefiendsGraspInterruptVoid();
                        PetGnawInterruptVoid();//晕的目标在8码内,才会使用晕去打断
                        PetStunEnemyHPVoid();
                        PetStunFriendHPVoid();
                        CancelAura(0x5f);//血95%时,取消转换
                    }
                    if (((THSettings.Instance.UsePauseKey && (THSettings.Instance.PauseKey != 0)) && ((GetAsyncKeyState(Keys.LControlKey) < 0) && (GetAsyncKeyState(IndexToKeys(THSettings.Instance.PauseKey)) < 0))) && (LastSwitch.AddSeconds(1.0) < DateTime.Now))
                    {
                        if (THSettings.Instance.Pause)
                        {
                            THSettings.Instance.Pause = false;
                            LastSwitch = DateTime.Now;
                            Logging.Write("Pause Mode is OFF, Hold 1 second Ctrl + " + IndexToKeys(THSettings.Instance.PauseKey) + " to Override bot action.");
                        }
                        else
                        {
                            THSettings.Instance.Pause = true;
                            THSettings.Instance.UpdateStatus = true;
                            LastSwitch = DateTime.Now;
                            Logging.Write("Pause Mode is ON, Hold 1 second Ctrl + " + IndexToKeys(THSettings.Instance.PauseKey) + " to resume bot action.");
                        }
                    }
                    if (Burst && (BurstLast < DateTime.Now))
                    {
                        Burst = false;
                        Logging.Write("Burst Mode is OFF");
                    }
                    if (((THSettings.Instance.BurstKey == 1) && !Burst) && (Me.Combat && !DebuffCC(Me)))
                    {
                        BurstLast = DateTime.Now.AddSeconds(15.0);
                        Logging.Write("Burst Mode Activated On Cooldown");
                        Burst = true;
                    }
                    if ((((THSettings.Instance.BurstKey == 2) && !Burst) && (Me.Combat && Attackable(Me.CurrentTarget, 15))) && (Me.CurrentTarget.IsBoss && !DebuffCC(Me)))
                    {
                        BurstLast = DateTime.Now.AddSeconds(15.0);
                        Logging.Write("Burst Mode Activated On Cooldown (Boss Only)");
                        Burst = true;
                    }
                    if ((((THSettings.Instance.BurstKey == 3) && !Burst) && ((MeHasAura("Bloodlust") || MeHasAura("Heroism")) || (MeHasAura("Time Warp") || MeHasAura("Ancient Hysteria")))) && !DebuffCC(Me))
                    {
                        BurstLast = DateTime.Now.AddSeconds(15.0);
                        Logging.Write("Burst Mode Activated On Bloodlust/Heroism/Time Warp/Ancient Hysteria");
                        Burst = true;
                    }
                    if (((THSettings.Instance.BurstKey == 4) && !Burst) && DebuffCCDuration(Me, 3000.0, false))
                    {
                        BurstLast = DateTime.Now.AddSeconds(15.0);
                        Logging.Write("Burst Mode Activated on Lose Control");
                        Burst = true;
                    }
                    if (((THSettings.Instance.BurstKey == 5) && !Burst) && ((HealWeight(Me) < THSettings.Instance.BurstHP) && !DebuffCC(Me)))
                    {
                        BurstLast = DateTime.Now.AddSeconds(15.0);
                        Logging.Write("Burst Mode Activated on My Health Low");
                        Burst = true;
                    }
                    if ((((THSettings.Instance.BurstKey == 6) && !Burst) && (CurrentTargetAttackable(30.0, false, false) && !Me.CurrentTarget.IsPet)) && (((HealWeight(Me) > THSettings.Instance.UrgentHeal) && (Me.CurrentTarget.HealthPercent < THSettings.Instance.BurstHP)) && !DebuffCC(Me)))
                    {
                        BurstLast = DateTime.Now.AddSeconds(15.0);
                        Logging.Write("Burst Mode Activated on Enemy Health Low");
                        Burst = true;
                    }
                    if (((THSettings.Instance.BurstKey > 6) && (GetAsyncKeyState(Keys.LControlKey) < 0)) && ((GetAsyncKeyState(IndexToKeys(THSettings.Instance.BurstKey - 6)) < 0) && (LastSwitch.AddSeconds(1.0) < DateTime.Now)))
                    {
                        if (Burst)
                        {
                            Burst = false;
                            LastSwitch = DateTime.Now;
                            Logging.Write("Burst Mode is OFF, Hold 1 second Ctrl + " + IndexToKeys(THSettings.Instance.BurstKey - 6) + " to Turn Burst Mode ON.");
                        }
                        else if (!DebuffCC(Me))
                        {
                            Burst = true;
                            LastSwitch = DateTime.Now;
                            BurstLast = DateTime.Now.AddSeconds(15.0);
                            Logging.Write("Burst Mode is ON for 15 seconds, Hold 1 second Ctrl + " + IndexToKeys(THSettings.Instance.BurstKey - 6) + " to Turn Burst Mode OFF.");
                        }
                    }
                }
            }
        }

        #endregion

        #region Nested type: LockSelector

        /// <summary>
        /// This behavior wraps the child behaviors in a 'FrameLock' which can provide a big performance improvement 
        /// if the child behaviors makes multiple api calls that internally run off a frame in WoW in one CC pulse.
        /// </summary>
        //private class LockSelector : PrioritySelector
        //{
        //    delegate RunStatus TickDelegate(object context);

        //    TickDelegate _TickSelectedByUser;

        //    public LockSelector(params Composite[] children)
        //        : base(children)
        //    {
        //        if (THSettings.Instance.UseFrameLock)
        //            _TickSelectedByUser = TickWithFrameLock;
        //        else
        //            _TickSelectedByUser = TickNoFrameLock;
        //    }

        //    public override RunStatus Tick(object context)
        //    {
        //        return _TickSelectedByUser(context);
        //    }

        //    private RunStatus TickWithFrameLock(object context)
        //    {
        //        using (StyxWoW.Memory.AcquireFrame())
        //        {
        //            return base.Tick(context);
        //        }
        //    }

        //    private RunStatus TickNoFrameLock(object context)
        //    {
        //        return base.Tick(context);
        //    }

        //}

        #endregion

        #region MainRotation

        private static DateTime LastRotationTime;
        private static bool IsOverrideModeOn;
        private static WoWUnit MyLastTarget;
        private static readonly Stopwatch sw = Stopwatch.StartNew();

        private static Composite MainRotation()
        {
            return new PrioritySelector(
                new Action(delegate
                    {
                        if ((LastWriteDebug < DateTime.Now) && (GetAsyncKeyState(Keys.F10) != 0))
                        {
                            LastWriteDebug = DateTime.Now + TimeSpan.FromSeconds(5.0);
                            Styx.Common.Logging.Write("=============================");
                            Styx.Common.Logging.Write("SpellsCooldownCache");
                            object[] args = new object[] { (DateTime.Now + SpellManager.GlobalCooldownLeft).ToString("ss:fff"), DateTime.Now.ToString("ss:fff") };
                            Styx.Common.Logging.Write("{1} GCDBack {0}", args);
                            foreach (KeyValuePair<string, DateTime> pair in SpellsCooldownCache)
                            {
                                Styx.Common.Logging.Write("{2}: {0} - {1}", new object[] { pair.Key, pair.Value.ToString("ss:fff"), DateTime.Now.ToString("ss:fff") });
                            }
                            Styx.Common.Logging.Write("=============================");
                        }
                        if (GetAsyncKeyState(Keys.F9) != 0)
                        {
                            Styx.Common.Logging.Write("=============================");
                            object[] objArray3 = new object[1];
                            TimeSpan span = (TimeSpan) (DateTime.Now - LastRotationTime);
                            objArray3[0] = span.TotalMilliseconds;
                            Styx.Common.Logging.Write("LastRotationTime take {0} ms", objArray3);
                            LastRotationTime = DateTime.Now;
                            Styx.Common.Logging.Write("=============================");
                        }
                        if ((LastWriteDebug < DateTime.Now) && (GetAsyncKeyState(Keys.F8) != 0))
                        {
                            int num = 1;
                            Styx.Common.Logging.Write("=============================");
                            num = 1;
                            Styx.Common.Logging.Write("NearbyFriendlyPlayers");
                            foreach (WoWUnit unit in NearbyFriendlyPlayers)
                            {
                                Styx.Common.Logging.Write(num + ". " + unit.SafeName);
                                num++;
                            }
                            Styx.Common.Logging.Write("=============================");
                            num = 1;
                            Styx.Common.Logging.Write("NearbyFriendlyUnits");
                            foreach (WoWUnit unit2 in NearbyFriendlyUnits)
                            {
                                Styx.Common.Logging.Write(num + ". " + unit2.SafeName);
                                num++;
                            }
                            Styx.Common.Logging.Write("=============================");
                            num = 1;
                            Styx.Common.Logging.Write("FarFriendlyPlayers");
                            foreach (WoWUnit unit3 in FarFriendlyPlayers)
                            {
                                Styx.Common.Logging.Write(num + ". " + unit3.SafeName);
                                num++;
                            }
                            Styx.Common.Logging.Write("=============================");
                            num = 1;
                            Styx.Common.Logging.Write("FarFriendlyUnits");
                            foreach (WoWUnit unit4 in FarFriendlyUnits)
                            {
                                Styx.Common.Logging.Write(num + ". " + unit4.SafeName);
                                num++;
                            }
                            Styx.Common.Logging.Write("=============================");
                            num = 1;
                            Styx.Common.Logging.Write("NearbyUnFriendlyPlayers");
                            foreach (WoWUnit unit5 in NearbyUnFriendlyPlayers)
                            {
                                Styx.Common.Logging.Write(num + ". " + unit5.SafeName);
                                num++;
                            }
                            Styx.Common.Logging.Write("=============================");
                            num = 1;
                            Styx.Common.Logging.Write("NearbyUnFriendlyUnits");
                            foreach (WoWUnit unit6 in NearbyUnFriendlyUnits)
                            {
                                Styx.Common.Logging.Write(num + ". " + unit6.SafeName);
                                num++;
                            }
                            Styx.Common.Logging.Write("=============================");
                            num = 1;
                            Styx.Common.Logging.Write("FarUnFriendlyPlayers");
                            foreach (WoWUnit unit7 in FarUnFriendlyPlayers)
                            {
                                Styx.Common.Logging.Write(num + ". " + unit7.SafeName);
                                num++;
                            }
                            Styx.Common.Logging.Write("=============================");
                            num = 1;
                            Styx.Common.Logging.Write("FarUnFriendlyUnits");
                            foreach (WoWUnit unit8 in FarUnFriendlyUnits)
                            {
                                Styx.Common.Logging.Write(num + ". " + unit8.SafeName);
                                num++;
                            }
                        }
                        if ((LastWriteDebug < DateTime.Now) && (GetAsyncKeyState(Keys.F7) != 0))
                        {
                            LastWriteDebug = DateTime.Now + TimeSpan.FromSeconds(5.0);
                            Styx.Common.Logging.Write("=============================");
                            foreach (WoWAura aura in Me.GetAllAuras())
                            {
                                Styx.Common.Logging.Write("{0} {1}", new object[] { aura.Name, aura.SpellId });
                            }
                            Styx.Common.Logging.Write("=============================");
                            if (BasicCheck(Me.CurrentTarget))
                            {
                                Styx.Common.Logging.Write("Me.CurrentTarget.GetAllAuras()");
                                foreach (WoWAura aura2 in Me.CurrentTarget.GetAllAuras())
                                {
                                    Styx.Common.Logging.Write("{0} {1} {2} {3} {4}", new object[] { aura2.Name, aura2.SpellId, aura2.CreatorGuid, MeGuid, Me.Guid });
                                }
                                Styx.Common.Logging.Write("=============================");
                            }
                        }
                        CurrentTargetCheck();
                        return RunStatus.Failure;
                    }),
                    Hold(),
                    GetUnits(),
                    new Decorator(
                        ret => THSettings.Instance.Pause,
                        new Action(delegate { return RunStatus.Success; })),
                    new Decorator(
                        ret => THSettings.Instance.UpdateStatus,
                        new Action(delegate { return RunStatus.Success; })),
                    //Trying to stop bot movement while casting
                    new Decorator(
                        ret =>
                        TreeRoot.Current.Name != "Tyrael" &&
                        TreeRoot.Current.Name != "LazyRaider" &&
                        TreeRoot.Current.Name != "Raid Bot" &&
                        TreeRoot.Current.Name != "Combat Bot" &&
                        Me.IsCasting,
                        new Action(delegate { return RunStatus.Success; })
                        ),
                    new Action(delegate
                        {
                            if (!IsOverrideModeOn &&
                                //Do not stop movement in LazyRaider if SMoveToTarget enabled
                                //TreeRoot.Current.Name != "LazyRaider" &&
                                (GetAsyncKeyState(Keys.LButton) < 0 &&
                                 GetAsyncKeyState(Keys.RButton) < 0) ||
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.StrafleLeft)) < 0 &&
                                IndexToKeys(THSettings.Instance.StrafleLeft) != Keys.None ||
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.Forward)) < 0 &&
                                IndexToKeys(THSettings.Instance.Forward) != Keys.None ||
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.StrafleRight)) < 0 &&
                                IndexToKeys(THSettings.Instance.StrafleRight) != Keys.None ||
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.TurnLeft)) < 0 &&
                                IndexToKeys(THSettings.Instance.TurnLeft) != Keys.None ||
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.Backward)) < 0 &&
                                IndexToKeys(THSettings.Instance.Backward) != Keys.None ||
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.TurnRight)) < 0 &&
                                IndexToKeys(THSettings.Instance.TurnRight) != Keys.None)
                            {
                                //Logging.Write(LogLevel.Diagnostic, "Override mode on. Stop all bot movement");
                                IsOverrideModeOn = true;
                            }

                            if (IsOverrideModeOn &&
                                //Do not stop movement in LazyRaider if SMoveToTarget enabled
                                //TreeRoot.Current.Name != "LazyRaider" &&
                                (GetAsyncKeyState(Keys.LButton) >= 0 ||
                                 GetAsyncKeyState(Keys.RButton) >= 0) &&
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.StrafleLeft)) >= 0 &&
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.Forward)) >= 0 &&
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.StrafleRight)) >= 0 &&
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.TurnLeft)) >= 0 &&
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.Backward)) >= 0 &&
                                GetAsyncKeyState(IndexToKeys(THSettings.Instance.TurnRight)) >= 0)
                            {
                                //Logging.Write(LogLevel.Diagnostic, "Override mode off. Bot movement resume");
                                IsOverrideModeOn = false;
                            }

                            //Get target back after a fear
                            if (Me.CurrentTarget != null && Me.CurrentTarget.IsValid && MyLastTarget != Me.CurrentTarget)
                            {
                                MyLastTarget = Me.CurrentTarget;
                            }

                            //Clear Target if dead and still in combat
                            if (Me.CurrentTarget != null && !Me.CurrentTarget.IsPlayer && !Me.CurrentTarget.IsAlive &&
                                Me.Combat)
                            {
                                Lua.DoString("RunMacroText(\"/cleartarget\")");
                            }

                            //Clear Target if walk away from friendly
                            //if (Me.CurrentTarget != null && !Me.CurrentTarget.IsPlayer &&
                            //    Me.CurrentTarget.IsFriendly &&
                            //    Me.CurrentTarget.IsSafelyBehind(Me))
                            //{
                            //    Lua.DoString("RunMacroText(\"/cleartarget\")");
                            //}

                            //Clear Backlist Target
                            if (Me.CurrentTarget != null &&
                                Blacklist.Contains(Me.CurrentTarget.Guid, BlacklistFlags.All))
                            {
                                Lua.DoString("RunMacroText(\"/cleartarget\")");
                            }

                            //Death Knight Dark Simulacrum
                            //if (Me.HasAura("Dark Simulacrum"))
                            //{
                            //    CastSpell("Seal of Insight", Me);
                            //    return RunStatus.Success;
                            //}
                            //ObjectManager.Update();
                            //GetUnits();

                            return RunStatus.Failure;
                        }),
                    SetAutoAttack(),
                    UseRacial(),
                    UseTrinket(),
                    UseProfession(),
                    new Decorator(ret => (UseSpecialization == 2) && !Me.Mounted, FrostRotation()),
                    new Decorator(ret => (UseSpecialization == 1) && !Me.Mounted, BloodRotation()),
                    new Decorator(ret => (UseSpecialization == 3) && !Me.Mounted, UnholyRotation())
                    //Dismount() 
                    );
        }

        #endregion
    }
}